package wre.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.constraint.Unique;
import org.supercsv.cellprocessor.ift.CellProcessor;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

/**
 * The Class RetortDAO contains all of the methods for getting an instance of the 
 * retort database that can also populate the database as well.
 * 
 * @author Adam Smith
 * 	
 */
public class RetortDAO {
	
	/**
	 * The main method.
	 * This method gets a private instance of the dataservice and populates the
	 * data structures with the data that is in the data service.
	 *
	 * @param args the arguments
	 */
	public static void main(String[] args) {
		RetortDAO dao = getInstance();
		dao.writeData();
	}

	/** The retorts. */
	private Map<Integer, String> retorts;
	
	/** The Constant processors. */
	private final static CellProcessor[] processors = new CellProcessor[] {
			new Unique(new ParseInt()), new StrMinMax(1, 100) };
	
	/** The Constant FILENAME. */
	private static final String FILENAME = "retort.csv";
	
	/** The Constant HEADER. */
	private static final String[] HEADER = new String[] { "id", "retort" };

	/**
	 * Gets the single instance of RetortDAO.
	 *
	 * @return single instance of RetortDAO
	 */
	public static RetortDAO getInstance() {
		RetortDAO retortDAO = new RetortDAO();
		PreparedQuery query = retortDAO.datastore.prepare(new Query(
				"RetortEntity"));
		for (Entity result : query.asIterable()) {
			retortDAO.retorts.put(((Long) result.getProperty("id")).intValue(),
					(String) result.getProperty("retort"));
		}
		return retortDAO;
	}

	/** The datastore. */
	private DatastoreService datastore;


	/**
	 * Instantiates a new retort dao that can only be grabbed from as a method
	 * call within this class
	 */
	private RetortDAO() {
		datastore = DatastoreServiceFactory.getDatastoreService();
		retorts = new HashMap<Integer, String>();
	}

	/**
	 * This method takes in a string that is representative of a retort and 
	 * adds the retort to the HashMap by using the String class hashCode() method
	 *
	 * @param retort the retort
	 */
	public void addRetort(String retort) {
		int id = retort.hashCode();
		retorts.put(id, retort);
	}

	/**
	 * This method deletes all of the retorts in the database
	 */
	public void deleteAll() {
		PreparedQuery query = datastore.prepare(new Query("RetortEntity"));
		for (Entity result : query.asIterable()) {
			datastore.delete(result.getKey());
		}
	}

	/**
	 * Gets the retort using an integer.
	 *
	 * @param retortId the retort id
	 * @return the retort
	 */
	public String getRetort(int retortId) {
		return retorts.get(retortId);
	}

	/**
	 * Gets all of the retorts in the map
	 *
	 * @return the retorts
	 */
	public Map<Integer, String> getRetorts() {
		return retorts;
	}

	/**
	 * Sets all of the retorts to the Map of retorts that is passed in
	 *
	 * @param retorts the retorts
	 */
	public void setRetorts(Map<Integer, String> retorts) {
		this.retorts = retorts;
	}

	/**
	 * This method takes all of the retorts from the Map and writes the data out to the 
	 * datastore
	 */
	public void writeData() {
		List<Entity> newRetorts = new ArrayList<Entity>();
		Iterator<Entry<Integer, String>> iterator = retorts.entrySet()
				.iterator();
		while (iterator.hasNext()) {
			Entry<Integer, String> entry = iterator.next();
			Entity entity = new Entity("RetortEntity");
			entity.setProperty("id", entry.getKey().hashCode());
			entity.setProperty("retort", entry.getValue());
			newRetorts.add(entity);
			// }
		}

		datastore.put(newRetorts);
	}
}
